package cn.lingyangwl.agile.infra.datamanage.controller;

import cn.lingyangwl.agile.infra.datamanage.db.DBConnect;
import cn.lingyangwl.agile.infra.datamanage.db.DbType;
import cn.lingyangwl.agile.infra.datamanage.db.GeneratorConfig;
import cn.lingyangwl.agile.infra.module.datamanage.db.*;
import cn.lingyangwl.agile.infra.datamanage.mode.entity.DatasourceConfig;
import cn.lingyangwl.agile.infra.datamanage.mode.rqrs.DatasourceConfigQuery;
import cn.lingyangwl.agile.infra.datamanage.mode.rqrs.DatasourceResp;
import cn.lingyangwl.agile.infra.datamanage.mode.rqrs.DbTableReq;
import cn.lingyangwl.agile.infra.datamanage.service.DatasourceService;
import cn.lingyangwl.agile.ram.ActionType;
import cn.lingyangwl.agile.ram.RamResource;
import cn.lingyangwl.framework.core.response.Resp;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author shenguangyang
 */
@Api(tags = "在线开发-数据源")
@RestController
@RequestMapping("/dataSource")
@RequiredArgsConstructor
public class DatasourceConfigController {
    private final DatasourceService datasourceService;

    @PostMapping("/saveDataSource")
    @RamResource(action = "onlineDev:dataSource:save", name = "在线开发-保存数据源", type = ActionType.WRITE)
    public Resp<?> saveDataSource(@RequestBody DatasourceConfig datasourceConfig) {
        datasourceService.save(datasourceConfig);
        return Resp.ok();
    }

    @GetMapping("/listAllDataSource")
    @RamResource(action = "onlineDev:dataSource:query", name = "在线开发-查询数据源", type = ActionType.READ)
    public Resp<List<DatasourceResp>> listAllDataSource() {
        List<DatasourceResp> datasourceConfigList = datasourceService.listAll();
        return Resp.ok(datasourceConfigList);
    }

    @GetMapping("/getDataSource")
    @RamResource(action = "onlineDev:dataSource:query", name = "在线开发-查询数据源", type = ActionType.READ)
    public Resp<DatasourceConfig> getDataSource(@RequestParam("id") Long id) {
        DatasourceConfig datasourceConfig = datasourceService.getById(id);
        return Resp.ok(datasourceConfig);
    }

    @GetMapping("/pageDataSource")
    @RamResource(action = "onlineDev:dataSource:query", name = "在线开发-查询数据源", type = ActionType.READ)
    public Resp<IPage<DatasourceConfig>> pageDataSource(DatasourceConfigQuery rq) {
        IPage<DatasourceConfig> datasourceConfigList = datasourceService.page(rq);
        return Resp.ok(datasourceConfigList);
    }

    @PostMapping("/updateDataSource")
    @RamResource(action = "onlineDev:dataSource:update", name = "在线开发-更新数据源", type = ActionType.WRITE)
    public Resp<?> updateDataSource(@RequestBody DatasourceConfig datasourceConfig) {
        datasourceService.update(datasourceConfig);
        return Resp.ok();
    }

    @DeleteMapping("/deleteDataSource")
    @RamResource(action = "onlineDev:dataSource:delete", name = "低代码-删除数据源", type = ActionType.WRITE)
    public Resp<?> deleteDataSource(@RequestBody DatasourceConfig datasourceConfig) {
        datasourceService.delete(datasourceConfig);
        return Resp.ok();
    }

    @DeleteMapping("/batchDeleteDataSource")
    @RamResource(action = "onlineDev:dataSource:delete", name = "低代码-删除数据源", type = ActionType.WRITE)
    public Resp<?> batchDeleteDataSource(@RequestParam("ids") List<Long> ids) {
        datasourceService.deleteBatchByIds(ids);
        return Resp.ok();
    }

    @GetMapping("/listTable")
    @RamResource(action = "onlineDev:dataSource:delete", name = "低代码-查询数据库表", type = ActionType.READ)
    public Resp<?> listTable(@Validated DbTableReq req) {
        List<TableDefinition> list = datasourceService.listTable(req);
        return Resp.ok(list);
    }

    @PostMapping("/testConnection")
    @RamResource(action = "onlineDev:dataSource:testConnection", name = "低代码-测试数据库连接", type = ActionType.READ)
    public Resp<?> testConnection(@RequestBody DatasourceConfig datasourceConfig) {
        String error = DBConnect.testConnection(GeneratorConfig.build(datasourceConfig));
        if (error != null) {
            return Resp.fail(error);
        }
        return Resp.ok();
    }

    @PostMapping("/dbtype")
    public Resp<List<DbTypeShow>> dbType(@RequestBody DatasourceConfig datasourceConfig) {
        List<DbTypeShow> dbTypeShowList = Stream.of(DbType.values())
                .map(dbType -> new DbTypeShow(dbType.getDisplayName(), dbType.getType()))
                .collect(Collectors.toList());
        return Resp.ok(dbTypeShowList);
    }

    /**
     * 通过指定的数据源获取数据库表
     */
    @GetMapping(value = "/listSqlContext")
    public Resp<List<SQLContext>> listSqlContext(@RequestParam("datasourceId") Long datasourceId,
                                          @RequestParam("tableNames") List<String> tableNames) {
        return Resp.ok(datasourceService.listSqlContext(datasourceId, tableNames));
    }

    @Getter
    @Setter
    @AllArgsConstructor
    private static class DbTypeShow {
        private String label;
        private Integer dbType;
    }
}
